from django.shortcuts import render

# Create your views here.
#登录用户，获取地址信息（查询用户所有地址，对象列表转换成字典）
#获取商品列表（redis),连接redis(hash和set获取),遍历选中商品id，查询信息，转换为字典。返回

from common.views import LoginRequiredJSONMixin
from django.views import View
from apps.users.models import Address
from django_redis import get_redis_connection
from apps.goods.models import SKU
from django.http import JsonResponse
import json,time
from apps.orders.models import OrderInfo,OrderGoods
from decimal import Decimal
from django.utils import timezone
from django.db import transaction
"""
0.登录用户
1.获取地址信息
    1.1 查询登录用户的所有地址信息
    1.2 将对象列表转换为字典列表
2.获取商品列表（redis 选中的商品信息）
    2.1 连接redis
    2.2 hash获取
    2.3 set获取
    2.4 遍历选中商品的id
    2.5 查询商品信息
    2.6 将对象转换为字典   
3. 返回响应

"""

class SettlementView(LoginRequiredJSONMixin,View):
    def get(self,request):
        user=request.user
        addresses=Address.objects.filter(user=user,is_deleted=False)
        address_list=[]
        for address in addresses:
            address_list.append({
                'id': address.id,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'place': address.place,
                'receiver': address.receiver,
                'mobile': address.mobile
            })

        redis_cli=get_redis_connection('cart')

        sku_id_counts=redis_cli.hgetall('cart_%s'%user.id)
        # #转换数据类型
        # redis_carts={}
        # for sku_id,count in sku_id_counts.items():
        #     redis_carts[int(sku_id)]=int(count)

        selected_ids=redis_cli.smembers('selected_%s'%user.id)

        skus=[]
        for sku_id in selected_ids:
            sku=SKU.objects.get(id=sku_id)

            skus.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'count': int(sku_id_counts[sku.id]),
                'price': sku.price
            })

        context={
            'addresses':address_list,
            'sku':skus,
            'freight':10
        }
        return JsonResponse({'code':0,'context':context,'errmsg':'done'})


class CommitView(LoginRequiredJSONMixin,View):
    def post(self,request):
        """

               一。接收数据
               地址id
               支付方式
               二。验证数据
               三。数据入库
                   1.OrderInfo -- 订单基本信息
                       1.1 获取用户信息
                       1.2 我们自己生成一个订单id（不用系统的自增）
                       1.3 价格数量运费新 -- 价格和总数量需要在新增订单商品的时候累加
                       1.4 订单状态 -- 订单状态和支付方式有关系
                   2.OrderGoods -- 订单商品信息
                       2.1 连接redis
                       2.2 获取hash
                       2.3 获取set数据 -- 选中的id
                       2.4 遍历选中的商品id
                       2.5 根据商品id查询商品信息
                       2.6 判断库存是否充足
                       2.7 如果充足，减少库存，增加销量
                       2.8 保存订单商品信息
                       2.9 计算 订单的价格和总数量
                   3. 更新订单总价格和总数量
                   4. 删除redis中选中的数据
               四。返回响应
               """
        data=json.loads(request.body.decode())
        address_id=data.get('address_id')
        pay_method=data.get('pay_method')

        if not all([address_id,pay_method]):
            return JsonResponse({'code':400,'errmsg':'参数错误'})

        try:
            address=Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return JsonResponse({'code':400,'errmsg':'参数错误'})
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'],OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return JsonResponse({'code':400,'errmsg':'参数错误'})

        user=request.user
        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + '%09d' % user.id
        # 价格 我们尽量使用 Decimal
        # Decimal 就是用来存储货币的
        freight = Decimal('10')
        total_price = Decimal('0')
        total_count = 0
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']: #货到付款
            status=OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:           # 支付宝
            status=OrderInfo.ORDER_STATUS_ENUM['UNPAID']

        with transaction.atomic():
            #事务 开始
            start_transation=transaction.savepoint()

            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                address=address,
                total_count=total_count,
                total_amount=total_price,
                freight=freight,
                pay_method=pay_method,
                status=status)

            redis_cli = get_redis_connection('carts')
            sku_id_counts = redis_cli.hgetall('carts_%s' % user.id) # {b'sku_id':b'count'}
            selected_ids = redis_cli.smembers('selected_%s' % user.id)
            # [b'sku_id']

            selected_carts = {}
            # {sku_id:count}
            for sku_id in selected_ids:
                selected_carts[int(sku_id)] = int(sku_id_counts[sku_id])

            ids = selected_carts.keys()
            for id in ids:

                while(True):
                #         2.5 根据商品id查询商品信息
                    sku = SKU.objects.get(id=id)
                    #         2.6 判断库存是否充足
                    # 获取用户购买的数量
                    custom_count = selected_carts[id]
                    if custom_count > sku.stock:
                        #出现问题，事务回滚回到开始
                        transaction.savepoint_rollback(start_transation)

                        return JsonResponse({'code': 400, 'errmsg': '购买量太大，库存不足'})
                       #         2.7 如果充足，减少库存，增加销量
                    time.sleep(10)


                    # sku.stock -= custom_count
                    # sku.sales += custom_count
                    # sku.save()

                    # 乐观锁
                    old_stock=sku.stock#查询库存
                    result=SKU.objects.filter(id=id,stock=old_stock).update(
                        stock=sku.stock-custom_count,sales=sku.sales+custom_count
                    )#对比更新前

                    if result == 0:
                        continue
                        # transaction.savepoint_rollback(start_transation)
                        # return JsonResponse({'code':400,'errmsg':'下单失败'})

                #乐观锁+事务隔离级别(读取已提交）
                    OrderGoods.objects.create(
                        order=order,
                        sku=sku,
                        count=custom_count,
                        price=sku.price
                    )
                    order.total_count += custom_count
                    order.total_amount += (custom_count * sku.price)
                    break
                #     3. 更新订单总价格和总数量
            order.save()
            #没有问题，事务提交，也提交开始
            transaction.savepoint_commit(start_transation)
                # 删除redis选中数据
                #hash   HDEL
            redis_cli.hdel('carts_%s'%user.id,*ids)
            #set
            redis_cli.srem('selected_%s'%user.id,*ids)

            return JsonResponse({'code':0,'order_id':order.order_id,'errmsg':'done'})















